package org.example.dingtalkintegrationservice.dingtalk.process;
import com.aliyun.dingtalkworkflow_1_0.Client;
import com.aliyun.dingtalkworkflow_1_0.models.FormComponent;
import com.aliyun.dingtalkworkflow_1_0.models.FormComponentProps;
import com.aliyun.dingtalkworkflow_1_0.models.SaveProcessHeaders;
import com.aliyun.dingtalkworkflow_1_0.models.SaveProcessRequest;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import org.example.dingtalkintegrationservice.exception.DingTalkCallExceptionGroovy;
import org.example.dingtalkintegrationservice.exception.WrongFormatExceptionGroovy;
import org.example.dingtalkintegrationservice.pojo.IdRecord;
import org.example.dingtalkintegrationservice.pojo.form.Form;
import org.example.dingtalkintegrationservice.pojo.form.Form.TableField;
import org.example.dingtalkintegrationservice.repository.IdRecordRepository;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
/**
 * @author pc
 */
@Component
public class CreateProcess {
    @Resource
    IdRecordRepository idRecordRepository;
    static Client createClient() {
        Config config = new Config();
        config.protocol = "https";
        config.regionId = "central";
        try{
            return new Client(config);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    static FormComponent getTextComponent(String label){
//        String label=jsonObject.label

        FormComponentProps formComponentProps1 = new FormComponentProps()
                .setComponentId(UUID.randomUUID().toString())
                .setPlaceholder("请输入")
                .setLabel(label)
                .setRequired(true);
        return new FormComponent()
                .setComponentType("TextField")
                .setProps(formComponentProps1);
    }
    static FormComponent getTableComponent(TableField jsonObject){
        var jsonChildren=jsonObject.children;
        String label=jsonObject.label;
        var childrenComponents=new ArrayList<FormComponent>();
        jsonChildren.forEach(
                child->{
                    childrenComponents.add(getTextComponent(child.label));
                }
        );
        FormComponentProps formComponentProps12 = new FormComponentProps()
                .setComponentId(UUID.randomUUID().toString())
                .setUpper("0")
                .setTableViewMode("table")
                .setLabel(label);
        return new FormComponent()
                .setComponentType("TableField")
                .setProps(formComponentProps12)
                .setChildren(childrenComponents);
    }
    static SaveProcessRequest init( String name, String description, String content) throws JsonProcessingException {
        Form form=new Form();
        form.fields= new ObjectMapper().readValue(content, new TypeReference<List<Form.Field>>() {} );
        String repeated=form.repeated();
        if (!"no".equals(repeated)){
            throw new WrongFormatExceptionGroovy(repeated,null,"examineFormFieldRepeated");
        }
        var components=new ArrayList<FormComponent>();
        form.fields.forEach(it->{
            if(it instanceof Form.TextField) {
                components.add(getTextComponent(it.label));
            } else if (it instanceof TableField) {
                components.add(getTableComponent((TableField) it));
            }
        }) ;
        var callBack=new SaveProcessRequest.SaveProcessRequestProcessFeatureConfigFeaturesCallback()
                .setApiKey("apitest1031").setAppUuid("dingdd7e3fc5e5f67a9235c2f4657eb6378f").setVersion("1");
        var feature=new SaveProcessRequest.SaveProcessRequestProcessFeatureConfigFeatures()
                .setName("TASK_EXECUTE").setRunType("ORIGIN").setCallback(callBack);
        var processFeatureConfig=new SaveProcessRequest.SaveProcessRequestProcessFeatureConfig().setFeatures(
                Collections.singletonList(feature)
        );
        return new SaveProcessRequest()
                .setName(name)
                .setDescription(description)
                .setFormComponents(components)
                .setProcessFeatureConfig(processFeatureConfig);
    }
    static String createProcess(String token, String name, String description, String content) throws Exception {
        SaveProcessRequest saveProcessRequest=init(name,description,content);
        Client client = createClient();
        SaveProcessHeaders saveProcessHeaders = new SaveProcessHeaders();
        saveProcessHeaders.xAcsDingtalkAccessToken = token;
        var res=client.saveProcessWithOptions(saveProcessRequest, saveProcessHeaders, new RuntimeOptions());
        if (res.statusCode!=200){
            throw new DingTalkCallExceptionGroovy(res.body.toString());
        }
        return res.body.result.processCode;
    }
    static String updateProcess(String token, String name, String description, String content,String processId) throws Exception {
        SaveProcessRequest saveProcessRequest=init(name,description,content);
        Client client = createClient();
        SaveProcessHeaders saveProcessHeaders = new SaveProcessHeaders();
        saveProcessHeaders.xAcsDingtalkAccessToken = token;
        saveProcessRequest.setProcessCode(processId);
        var res=client.saveProcessWithOptions(saveProcessRequest, saveProcessHeaders, new RuntimeOptions());
        if (res.statusCode!=200){
            throw new DingTalkCallExceptionGroovy(res.body.toString());
        }
        return res.body.result.processCode;
    }
    String create(String classCode,String token,String name,String description,String input) throws Exception {
        var output = createProcess(token, name, description, input);
        IdRecord idRecord=new IdRecord("/createProcess",name,classCode,output,"create",input);
        idRecordRepository.save (idRecord);
        return output;
    }
    String update(String classCode,String token,String name,String description,String processId,String input) throws Exception {
        var output = updateProcess(token, name, description, input,processId);
        IdRecord idRecord=new IdRecord("/createProcess",name,classCode,output,"update",input);
        idRecordRepository.save(idRecord);
        return output;
    }
    public String exec(String classCode,String token, String name, String description,String input) throws Exception {
        var idRecord = idRecordRepository.findLatestById1(classCode);
        if (idRecord.isPresent()) {
            String processId = idRecord.get().getId2();
            if (input.equals(idRecord.get().getExt())){
                return processId;
            }
            return update(classCode,token, name, description, processId, input);
        } else {
            return create(classCode,token, name, description, input);
        }
    }
}